package com.tvunetworks.center.device.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.model.SearchDeviceParam;
import com.tvunetworks.center.common.model.dto.CheckAuthDTO;
import com.tvunetworks.center.common.model.dto.instance.ApiParam;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.device.constant.DeviceApiConstant;
import com.tvunetworks.center.device.model.GridMetadata;
import com.tvunetworks.center.device.model.MyDevice;
import com.tvunetworks.center.device.model.vo.DeviceApiParam;
import com.tvunetworks.center.device.model.vo.UserDeviceStructure;
import com.tvunetworks.center.device.model.vo.VoDevice;
import com.tvunetworks.center.device.service.DeviceApiService;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.GridMetadataService;
import com.tvunetworks.center.device.service.UserDeviceService;
import com.tvunetworks.center.device.service.feign.AccessFeignService;
import com.tvunetworks.center.device.service.feign.UserFeignService;
import com.tvunetworks.center.gs.model.Device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @program: tvucc-aggregator
 * @description: deviceapi实现层
 * @author Kevin_Li
 * @create: 2019-10-10 12:42
 **/
@Slf4j
@Service
public class DeviceApiServiceImpl implements DeviceApiService {


    @Autowired
    private AccessFeignService accessFeignService;
    @Autowired
    private UserFeignService userFeignService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private GridMetadataService gridMetadataService;
    @Autowired
    private UserDeviceService userDeviceService;
    @Autowired
    private ExtServiceImpl extService;

    @Override
    public Result getDeviceListByUser(DeviceApiParam deviceApiParam) {
        String type = deviceApiParam.getType();
        String session = deviceApiParam.getSession();
        SearchDeviceParam searchType = new SearchDeviceParam();
        searchType.setLiving(true);
        searchType.setOnline(true);
        searchType.setOffline(true);
        searchType.setNoCamera(true);
        searchType.setBookmardIds("All");
        searchType.setUnClassified(true);
        searchType.setToken(true);
        searchType.setCondition(deviceApiParam.getCondition());
        if (type.equalsIgnoreCase(DeviceApiConstant.XML_PARAM)) {
            //XML的需要手动checkAuth
            Result<Void> checkAuthResult = checkAuth(deviceApiParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
            //通过session那用户信息
            Result<LoginUser> loginUser = userFeignService.getLoginUser(session);
            log.error("getLoginUser result:" + loginUser);
            if (!ResultUtil.SUCCESS.equals(loginUser.getErrorCode())) {
                return loginUser;
            }
            LoginUser loginUser1 = loginUser.getResult();
            List<Device> rList = userFeignService.listReceiverControlR(loginUser1.getId(), searchType);
            searchType.setPack(true);
            searchType.setAnywhere(true);
            searchType.setGridPack(true);
            searchType.setGridSdi(true);
            searchType.setExt(true);
            List<Device> tList = userFeignService.listUserSourceDevices(loginUser1.getId(), searchType);
            //get matrix switchtype
            try {
                for (Device device : rList) {
                    if (device.getType().toLowerCase().equals("m")) {
                        String switchtype = deviceService.getSwitchType("automation.", device.getPeerId());
                        if (switchtype.equals("1")) {
                            device.setRemark("1");
                        } else {
                            device.setRemark("2");
                        }
                    }
                }
            } catch (Exception e) {
                log.error(e.toString(), e);
            }
            return ResultUtil.success(new UserDeviceStructure(tList, rList));
        } else {
            //JSON方式请求 需要分页  加type过滤
            Result<LoginUser> loginUser = userFeignService.getLoginUserWithNoCheck(session);
            log.error("getLoginUser result:" + loginUser);
            if (!ResultUtil.SUCCESS.equals(loginUser.getErrorCode())) {
                return loginUser;
            }
            int everyPageNum = deviceApiParam.getEveryPageNum();
            if (everyPageNum > 200) {
                everyPageNum = 200;
            }
            //loginUser1是通过usersetvice直接返回的对象，里面的uesrId和CC中的id不一样
            LoginUser loginUser1 = loginUser.getResult();
            //userByEmail通过email在cc中获取对应的userId
            LoginUser userByEmail = userFeignService.getUserByEmail(loginUser1.getEmail());
            if (userByEmail == null){
                return ResultUtil.error("105", "not data");
            }
            searchType.setPack(deviceApiParam.isPack());
            searchType.setAnywhere(deviceApiParam.isAnyWhere());
            searchType.setGridPack(deviceApiParam.isGridPack());
            searchType.setGridSdi(deviceApiParam.isGridSdi());
            searchType.setExt(deviceApiParam.isExt());
            searchType.setReceiver(deviceApiParam.isReceiver());
            List<Device> resultList = new ArrayList<Device>();
            if (StringUtils.isBlank(userByEmail.getRole()) || userByEmail.getRole().equals("3") || userByEmail.getRole().equals("4")) {
                List<Device> tList = userFeignService.listUserSourceDevices(userByEmail.getId(), searchType);
                //由于listUserSourceDevices这个接口source和receiver都会返回,所有不用再调listReceiverControlR
//                List<Device> rList = null;
//                if (deviceApiParam.isReceiver()) {
//                    rList = userFeignService.listReceiverControlR(userByEmail.getId(), searchType);
//                }
                if (tList != null && tList.size() > 0) {
                    List<String> list = new ArrayList<>();
                    for (Device device : tList) {
                        if (device.getType().equals("X")) {
                            list.add(device.getPeerId());
                        }
                    }
                    if (list.size() > 0) {
                        Map<String, String> map = deviceService.listDeviceMetadata(list);
                        for (Device device : tList) {
                            if (!device.getType().equals("X")){

                                continue;
                            }
                            String metadata = map.get(device.getPeerId());
                            if (metadata != null) {
                                device.setMetaData(metadata);
                            }
                        }
                    }
                    resultList.addAll(tList);
                }
//                if (rList != null && rList.size() > 0) {
//                    resultList.addAll(rList);
//                }
            } else {
                resultList = deviceService.listAllDevices(searchType);
            }
            PageInfo<Device> pageInfo = new PageInfo<>();
            pageInfo.setPageNum(deviceApiParam.getCurrentPageNum());
            pageInfo.setPageSize(everyPageNum);
            PageInfo<Device> devicePageInfo = packagePageInfo(resultList, pageInfo);
            return ResultUtil.success(devicePageInfo);
        }
    }

    @Override
    public Result getGridMetadata(DeviceApiParam deviceApiParam) {
        String peerId = deviceApiParam.getPeerId();
            Result<Void> checkAuthResult = simplenessCheckAuth(deviceApiParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
        GridMetadata gridMetadata = gridMetadataService.getGridMetadataByPeerId(peerId);
        if (gridMetadata != null) {
            MyDevice dbDevice = deviceService.getDBDevice(peerId);
            if (dbDevice != null && StringUtils.isNotBlank(dbDevice.getMetaData())) {
                gridMetadata.setStorySlug(dbDevice.getMetaData());
            }
        }
        return ResultUtil.success(gridMetadata);
    }

    @Override
    public Result updateGridMetadata(DeviceApiParam deviceApiParam) {
        Result result = new Result<>();
        Result<Void> checkAuthResult = simplenessCheckAuth(deviceApiParam);
        if (!checkAuthResult.assertSuccess()) {
            return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
        }
        String type = deviceApiParam.getType();
        GridMetadata gridMetadata = deviceApiParam.getGridMetadata();
        if (!type.equalsIgnoreCase(DeviceApiConstant.XML_PARAM)) {
            //json需要检测location
            if (gridMetadata.getLocation() != null || gridMetadata.getLongitude() != null
                    || gridMetadata.getLatitude() != null) {
                if (gridMetadata.getLocation() == null || gridMetadata.getLongitude() == null
                        || gridMetadata.getLatitude() == null) {
                    log.error("Location information is incomplete");
                    result.setErrorCode("80050040");
                    result.setErrorInfo("Location information is incomplete");
                    return result;
                }
            }
        }
        Device device = deviceService.getCurrentDevice(gridMetadata.getPeerId());
        if (device == null){
            return ResultUtil.error("106", "device not exist");
        }

        gridMetadataService.updateGridMetadata(gridMetadata);
        return ResultUtil.success();
    }

    @Override
    public Result getStatus(DeviceApiParam deviceApiParam) {
        String type = deviceApiParam.getType();
        String peerIds = deviceApiParam.getPeerIds();
        if (type.equalsIgnoreCase(DeviceApiConstant.XML_PARAM)) {
            //XML的需要手动checkAuth
                Result<Void> checkAuthResult = simplenessCheckAuth(deviceApiParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
        }
        List<VoDevice> deviceList = new ArrayList<VoDevice>();
        if (StringUtils.isNotEmpty(peerIds)) {
            String[] peerIdArr = peerIds.split(",");
            for (String peerId : peerIdArr) {
                Device device = deviceService.getCurrentDevice(peerId.trim());
                VoDevice voDevice = new VoDevice();
                voDevice.setPeerId(peerId);
                if (device != null) {
                    voDevice.setStatus(device.getStatus());
                    voDevice.setVersion(device.getVersion());
                    voDevice.setLivePeerId(device.getLivePeerId() == null ? "" : device.getLivePeerId());
                    voDevice.setResultCode("0x0");
                } else {
                    voDevice.setResultCode("80050025");
                    voDevice.setResultDesc("Device not exist");
                }
                deviceList.add(voDevice);
            }
        }
        return ResultUtil.success(deviceList);
    }

    @Override
    public Result deleteExt(DeviceApiParam deviceApiParam) {
        String type = deviceApiParam.getType();
        if (type.equalsIgnoreCase(DeviceApiConstant.XML_PARAM)) {
            //XML的需要手动checkAuth
            Result<Void> checkAuthResult = simplenessCheckAuth(deviceApiParam);
            if (!checkAuthResult.assertSuccess()) {
                return ResultUtil.error(checkAuthResult.getErrorCode(), checkAuthResult.getErrorInfo());
            }
        }
        String peerId = deviceApiParam.getPeerId();
        Result<String> result = extService.deleteExt(peerId);
        if ("0x0".equals(result.getErrorCode())){

            return ResultUtil.success();
        }
        if ("101".equals(result.getErrorCode()) || "102".equals(result.getErrorCode())){

            return ResultUtil.error("80050004", "Source not found");
        }
        if ("103".equals(result.getErrorCode())){

            return ResultUtil.error("80050023", "Source on live");
        }
        return ResultUtil.success();
    }

    @Override
    public Result pageDevicesByUser(SearchDeviceParam param) {
        //JSON方式请求 需要分页  加type过滤
        Result<LoginUser> userLoginResult = userFeignService.getLoginUserWithNoCheck(param.getSession());
        log.error("getLoginUser result:" + userLoginResult);
        if (!userLoginResult.assertSuccess()) {
            return userLoginResult;
        }
        //loginUser1是通过usersetvice直接返回的对象，里面的uesrId和CC中的id不一样
        LoginUser loginUser = userLoginResult.getResult();
        param.setLiving(true);
        param.setOnline(true);
        param.setOffline(true);
        param.setNoCamera(true);
        param.setBookmardIds("All");
        param.setUnClassified(true);
        //JSON方式请求 需要分页  加type过滤
        int everyPageNum = param.getPageSize();
        if (everyPageNum > 200) {
            everyPageNum = 200;
        }
        //userByEmail通过email在cc中获取对应的userId
        LoginUser userByEmail = userFeignService.getUserByEmail(loginUser.getEmail());
        if (userByEmail == null) {
            return ResultUtil.error("105", "not data");
        }
        List<Device> resultList = new ArrayList<Device>();
        if (StringUtils.isBlank(userByEmail.getRole()) || userByEmail.getRole().equals("3") || userByEmail.getRole().equals("4")) {
            List<Device> tList = userFeignService.listUserSourceDevices(userByEmail.getId(), param);
            List<Device> rList = null;
            if (param.isReceiver()) {
                rList = userFeignService.listReceiverControlR(userByEmail.getId(), param);
            }
            if (!CollectionUtils.isEmpty(tList)) {
                List<String> list = new ArrayList<>();
                tList.forEach(s->{
                    if ("X".equals(s.getType())) {
                        list.add(s.getPeerId());
                    }
                });
                if (!CollectionUtils.isEmpty(list)) {
                    Map<String, String> map = deviceService.listDeviceMetadata(list);
                    tList.forEach(s->{
                        if (!"X".equals(s.getType())) {
                            return;
                        }
                        String metadata = map.get(s.getPeerId());
                        if (metadata != null) {
                            s.setMetaData(metadata);
                        }
                    });
                }
                resultList.addAll(tList);
            }
            if (!CollectionUtils.isEmpty(rList)) {
                resultList.addAll(rList);
            }
        } else {
            resultList = deviceService.listAllDevices(param);
        }
        //排序
        if (StringUtils.isNotEmpty(param.getOrderBy())) {
            this.sortDeviceByOrderBy(resultList, param.getOrderBy(), param.getSort());
        }

        PageInfo<Device> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(param.getPageNum());
        pageInfo.setPageSize(everyPageNum);
        PageInfo<Device> devicePageInfo = packagePageInfo(resultList, pageInfo);
        return ResultUtil.success(devicePageInfo);
    }

    /**
     * 对设备的集合进行排序
     * @param devices
     * @param orderBy
     * @param sort
     */
    private void sortDeviceByOrderBy(List<Device> devices, String orderBy, String sort) {
        if (CollectionUtils.isEmpty(devices)) {
            return;
        }
        if (StringUtils.isNotEmpty(orderBy)) {
            String[] orderBys = orderBy.split(",");
            String [] sorts;
            if (StringUtils.isNotEmpty(sort)) {
                sorts = sort.split(",");
            }else {
                sorts = new String[orderBys.length];
            }
            if (orderBys.length == 1) {
                if (StringUtils.equalsIgnoreCase("name", orderBys[0])) {
                    if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])) {
                        //降序
                       devices.sort(Comparator.comparing(Device::getName).reversed());
                    }else  {
                        devices.sort(Comparator.comparing(Device::getName));
                    }
                } else if (StringUtils.equalsIgnoreCase("peerId", orderBys[0])) {
                    if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])) {
                        //降序
                        devices.sort(Comparator.comparing(Device::getPeerId).reversed());
                    }else  {
                        devices.sort(Comparator.comparing(Device::getPeerId));
                    }
                }
            }else {
                if (StringUtils.equalsIgnoreCase("name", orderBys[0])) {
                    if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])
                            && StringUtils.isNotEmpty(sorts[1]) && StringUtils.equalsIgnoreCase("1", sorts[1])) {
                        //同时降序
                        devices.sort(Comparator.comparing(Device::getName).reversed().thenComparing(Comparator.comparing(Device::getPeerId).reversed()));
                    } else if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])) {
                        //第一个降序，第二个升序
                        devices.sort(Comparator.comparing(Device::getName).reversed().thenComparing(Device::getPeerId));
                    }else if(StringUtils.isNotEmpty(sorts[1]) && StringUtils.equalsIgnoreCase("1", sorts[1])){
                        //第一个升序，第二个降序
                        devices.sort(Comparator.comparing(Device::getName).thenComparing(Comparator.comparing(Device::getPeerId).reversed()));
                    }else {
                        //同时升序
                        devices.sort(Comparator.comparing(Device::getName).thenComparing(Device::getPeerId));
                    }
                } else if (StringUtils.equalsIgnoreCase("peerId", orderBys[0])) {
                    if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])
                            && StringUtils.isNotEmpty(sorts[1]) && StringUtils.equalsIgnoreCase("1", sorts[1])) {
                        //1与2同时降序
                        devices.sort(Comparator.comparing(Device::getPeerId).reversed().thenComparing(Comparator.comparing(Device::getName).reversed()));
                    } else if (StringUtils.isNotEmpty(sorts[0]) && StringUtils.equalsIgnoreCase("1", sorts[0])) {
                        //第一个降序，第二个升序
                        devices.sort(Comparator.comparing(Device::getPeerId).reversed().thenComparing(Device::getName));
                    }else if(StringUtils.isNotEmpty(sorts[1]) && StringUtils.equalsIgnoreCase("1", sorts[1])){
                        //第一个升序，第二个降序
                        devices.sort(Comparator.comparing(Device::getPeerId).thenComparing(Comparator.comparing(Device::getName).reversed()));
                    }else {
                        //同时升序
                        devices.sort(Comparator.comparing(Device::getPeerId).thenComparing(Device::getName));
                    }
                }

            }

        }
    }


    private Result<Void> checkAuth(ApiParam apiParam) {

        CheckAuthDTO checkAuthDTO = apiParam.convertToCheckAutonotCheckTimestamp();
        checkAuthDTO.setFunction("default");
        try {
            return accessFeignService.checkAuth(checkAuthDTO);
        } catch (Exception e) {
            log.error("checkAuth exception", e);
            return ResultUtil.error("80050026", e.getMessage());
        }
    }

    private Result<Void> simplenessCheckAuth(ApiParam apiParam) {
        try {
            String appkey = apiParam.getAppkey();
            String signature = apiParam.getSignature();
            String timestamp = apiParam.getTimestamp();
            if (StringUtils.isBlank(appkey) || StringUtils.isBlank(signature) || StringUtils.isBlank(timestamp)){

                return ResultUtil.error("80050027", "check auth param error");
            }
            return accessFeignService.simplenessCheckAuth(apiParam.getAppkey(), apiParam.getSignature(), apiParam.getTimestamp());
        } catch (Exception e) {
            log.error("checkAuth exception", e);
            return ResultUtil.error("80050026", e.getMessage());
        }
    }


    private <T> PageInfo<T> packagePageInfo(List<T> list, PageInfo<T> pageInfo) {
        Page<T> page = new Page<>();

        if (list == null || list.size() == 0) {
            list = new ArrayList<>();
        }

        page.setPageNum(pageInfo.getPageNum())
                .setPageSize(pageInfo.getPageSize())
                .setTotal(list.size());
        page.addAll(subPageList(list, pageInfo));


        return new PageInfo<>(page, 8);

    }

    /**
     *
     * @param vs vs
     * @param pb pb
     * @param <T> t
     * @return List
     */
    protected <T> List<T> subPageList(List<T> vs, PageInfo<T> pb) {
        int pageIndex = pb.getPageNum();
        if (pageIndex < 1) {
            pageIndex = 1;
        }
        pb.setPageNum(pageIndex);
        if (vs.size() > 0 && ((pageIndex - 1) * pb.getPageSize()) < Math.min(pageIndex * pb.getPageSize(), vs.size())) {
            return vs.subList(((pageIndex - 1) * pb.getPageSize()),
                    Math.min(pageIndex * pb.getPageSize(), vs.size()));
        } else {
            return new ArrayList<>();
        }
    }
}
